/**
    @brief Module de gestion de la session, fichier source

    @file session.cpp
    @version 0.1
    @date 2009/01/10

*/

#include "session.h"
#include "../user/user.h"
#include "../ufile/ufile.h"
#include "../view/txtview.h"
#include "../view/gtkview.h"
#include "../filetree/filetree.h"
#include "../serializer/serializer.h"

Session::Session(int & argc, char **& argv) : currentUser("TestUser", "TestHost"), commonSer("common"), netengine( 2500 )
{
    com = NULL;
    groups = new Group();

    Gtk::Main kit(argc, argv);
    GtkView affichageGtk(argc, argv, this);
    Gtk::Main::run(*affichageGtk._mainwin());

    // session debug:
    cout << "end of session" << endl;
}

Session::~Session(void)
{
    // debug rezo:
    cout << "Sending Network stop signal" << endl;
    netengine.stop();
    cout << netengine.netStarted() << ": " << "if false network engine should have stopped now" << endl;

    cout << "Sauvegarde ..." << endl;
    //debug.printTree(localUserFiles);

    userSer.open('w');
    userSer.saveFileTree(userFiles);
    userSer.close();

    // delete groups;
}


int Session::start( string loginuser, string loginhost, unsigned int loginport )
{
    setUserName(loginuser);
    setUserHost(loginhost);
    setPort(loginport);

    /* Démarrage du serveur */
    com = netengine.start();


    /* Chargement fichier utilisateur */
    UFile userIndexFile(userSer._fileName(), &currentUser);
    if (userIndexFile.nodeExists())
    {
        userSer.loadFileTree();
        userSer.close();
        userFiles.setLocalFiles(userSer._newFileTree());
    }

    /* Chargement fichier commun */
    UFile commonIndexFile(commonSer._fileName(), &currentUser);
    if (commonIndexFile.nodeExists())
    {
        commonSer.loadFileTree();
        commonSer.close();
        commonFiles.setLocalFiles(commonSer._newFileTree());
    }

    /* Merge arbre utilisateur dans arbre commun */
    commonFiles.mergeWith(userFiles);

    //    TxtView debug;
    //    debug.printTree(commonFiles);

    return 0;
}

const Group* Session::_groups( void ) const
{
    return groups;
}

const User* Session::_currentUser(void) const
{
        return &currentUser;
}

const FileTree* Session::_userFiles( void ) const
{
    return &userFiles;
}

const FileTree* Session::_commonFiles( void ) const
{
    return &commonFiles;
}

const file_tree& Session::_userFilesTree( void ) const
{
    return userFiles._localFiles();
}

const file_tree& Session::_commonFilesTree( void ) const
{
    return commonFiles._localFiles();
}

void Session::setMergeWithCommonFiles( const FileTree& tree)
{
    commonFiles.mergeWith(tree);
}

void Session::setMergeWithUserFiles( const FileTree& tree)
{
    userFiles.mergeWith(tree);
}

void Session::indexUserFilesFolder( string path )
{
    userFiles.indexLocalFolder(path, &currentUser);
}

void Session::sendGroupToAll()
{
    user_group::iterator it, end;
    end = groups->_end();

    for ( it = groups->_firstUser(); it != end ; it++ )
    {
        cout << "sending group file to " << it->_nickname() << endl;
        string response;
        ClientSocket client(it->_address(), 2500);
        client >> response;
        client << "NEWGROUPFILE";
        client >> response;
        if( response == "CMDOK" )
        {
            client.sendFile("group-files");
        }
    }
}

void Session::getFileIndexFromAll()
{
    user_group::iterator it, end;
    end = groups->_end();

    for ( it = groups->_firstUser(); it != end ; it++ )
    {
        cout << "receiving index file from " << it->_nickname() << endl;
        string response;
        ClientSocket client(it->_address(), 2500);
        client >> response;
        client << "INDEXFILEREQUEST";
        client >> response;
        if( response == "CMDOK" )
        {
            client << it->_nickname()+"-files";
            client >> response;
            client.recvFile("distant-files");
        }
        // charger donnees et merger
        Serializer fileIndexLoader("distant");
        fileIndexLoader.open('r');
        fileIndexLoader.loadFileTree();
        fileIndexLoader.close();

        FileTree distantFiles;
        distantFiles.setLocalFiles( fileIndexLoader._newFileTree() );
        setMergeWithCommonFiles( distantFiles );
    }
}

void Session::getFile(string host, int port, string path, string name)
{
        string respmsg;

        ClientSocket filetransfer(host, 2500);
        filetransfer >> respmsg;
        filetransfer << "SENDFILEREQUEST";
        filetransfer >> respmsg;
        if(respmsg == "CMDOK")
        {
            filetransfer << path;
            filetransfer.recvFile(name);
            cout << "file received" << endl;
        }

        return;
}

void Session::showGroup()
{
    user_group::iterator it, end;
    end = groups->_end();

    for ( it = groups->_firstUser(); it != end ; it++ )
    {
        cout << it->_nickname() << " - " << it->_address() << endl;
    }
}

void Session::setUserName(string NewUserName)
{
    currentUser.setNickname(NewUserName);
    userSer.setFileName(currentUser._nickname()+userSer._extention());
}

void Session::setUserHost(string NewUserHost)
{
    userHost = NewUserHost;
    currentUser.setAddress(userHost);
}

void Session::setPort(unsigned int NewPort)
{
    sessionPort = NewPort;
    netengine.setPort(sessionPort);
}

void Session::setPipes(NetworkEngine::Pipes* pip)
{
    com = pip;
}
